在過去的幾篇文章中,我們探討了如何使用 CSS Modules 和 CSS 變數 來優化應用中的主題切換機制,並提高應用的靈活性和可維護性。今天,我們基於Figma 設計稿中介紹頁去設計一個靈活的按鈕元件,這個按鈕不僅支持多種狀態(例如正常、懸停、激活、禁用),還允許你自定義圖標的位置,並能夠在多國語言和主題切換的環境中保持一致的使用體驗。
按鈕是用戶與應用交互的重要界面元件,因此設計一個靈活且功能齊全的按鈕對整體 UI 的可用性至關重要。以下是我們的按鈕元件將支持的核心功能:
我們的按鈕元件可以通過以下屬性來靈活地控制樣式、圖標、大小和狀態:
| 屬性 | 說明 | 類型 | 預設值 | 
|---|---|---|---|
| type | 設置按鈕樣式類型( primary、secondary) | string | primary | 
| icon | 設置按鈕的圖標 | ReactNode | null | 
| iconPosition | 設置圖標的位置( left、right、top、bottom) | string | left | 
| afterContent | 設置 ::after的內容,通常用來顯示一些動態效果 | string | "" | 
| size | 設置按鈕的大小( small、medium、large) | string | medium | 
| isLoading | 加載中狀態(顯示加載動畫) | boolean | false | 
| isDisabled | 禁用狀態,按鈕變灰且無法點擊 | boolean | false | 
| children | 按鈕的文本或內容 | ReactNode | null | 
這些屬性讓我們的按鈕在設計上能夠靈活處理不同的使用場景,包括樣式控制、圖標設置、大小選擇、狀態切換等。
在 Light Mode 下,按鈕在各狀態的樣式變化如下圖所示:
prop-types 和react-icons為了在開發過程中進行屬性檢查,我們將安裝 prop-types 來確保按鈕接收到正確的屬性類型。另外,我們還將使用 react-icons 來為按鈕添加圖標。打開終端並運行以下命令:
npm install prop-types
npm install react-icons --save
接下來,我們開始編寫按鈕元件,首先定義它的基本屬性和默認值。
//src/components/buttons/button.jsx
import React from 'react';
import PropTypes from 'prop-types';
import * as styles from '@/components/buttons/Button.module.scss';
function Button({
    type = 'primary',
    icon,
    iconPosition = 'left',
    afterContent = '',
    size = 'medium',
    isLoading,
    isDisabled,
    children,
    ...props
}) {
說明:
type:這個屬性決定按鈕的樣式類型,例如 primary 表示主要按鈕,默認是 primary。icon 和 iconPosition:允許按鈕嵌入圖標,並提供圖標位置的選擇。icon 可以接受從 react-icons 庫中導入的圖標,例如:import { FaSave } from 'react-icons/fa';afterContent:用來定義按鈕的 ::after 內容,通常用於動態效果。size:按鈕大小控制,例如 small、medium 或 large。isLoading 和 isDisabled:這兩個屬性用來控制按鈕的狀態,分別表示按鈕是否處於加載狀態或禁用狀態。我們接下來根據傳入的屬性來動態生成按鈕的樣式,確保按鈕在不同狀態下能應用正確的樣式。
// 動態設置按鈕的圖標位置
    const buttonClasses = `
    ${styles.button} 
    ${styles[type]} 
    ${styles[size]} 
    ${isDisabled ? styles.disabled : ''}
  `;
這段代碼動態構建了按鈕的 CSS 類名。不同的 type 和 size 值會應用不同的樣式類別。當 isDisabled 為 true 時,按鈕將應用禁用樣式,使其無法點擊並變灰。
我們還需要為按鈕添加圖標功能,並根據圖標的位置來調整其顯示位置。
const iconClasses = `${styles.icon} ${styles[iconPosition]}`;
這裡,我們根據 iconPosition 的值來設置圖標的樣式類。圖標可以靈活地出現在按鈕的左側、右側、上方或下方。
這一部分是按鈕的主要 JSX 結構,根據 isLoading、icon 等屬性進行動態渲染。
jsx
複製程式碼
return (
    <button
        className={buttonClasses}
        disabled={isDisabled || isLoading}
        style={{ '--after-content': `url(${afterContent})` }}
        {...props}
    >
        {isLoading ? <span className={styles.loader}></span> : null}
        {/* 根據 iconPosition 動態渲染圖標 */}
        {icon && iconPosition === 'left' && <span className={iconClasses}>{icon}</span>}
        {children} {/* 傳入按鈕文本 */}
        {icon && iconPosition === 'right' && <span className={iconClasses}>{icon}</span>}
    </button>
);
說明:
disabled={isDisabled || isLoading}:如果按鈕處於禁用狀態或正在加載,它將被禁用以防止用戶進行交互。loader)。iconPosition,圖標會動態渲染在按鈕的左側或右側。children 屬性傳遞進來。prop-types 進行類型檢查使用 prop-types 來檢查傳遞給按鈕元件的屬性類型,保證我們在開發過程中能夠傳遞正確的屬性值。例如,如果我們錯誤地傳遞了一個數字作為 children,而不是字串或 React 元素,prop-types 會發出警告,讓開發者及時修正錯誤。
Button.propTypes = {
    children: PropTypes.node.isRequired,
    type: PropTypes.oneOf(['primary', 'secondary']),
    icon: PropTypes.string,
    iconPosition: PropTypes.oneOf(['left', 'right', 'top', 'bottom']),
    afterContent: PropTypes.string,
    size: PropTypes.oneOf(['small', 'medium', 'large']),
    isLoading: PropTypes.bool,
    isDisabled: PropTypes.bool,
};
今天我們深入探討了如何設計一個靈活且高效的 React 按鈕元件,並通過多種屬性(如圖標位置、按鈕狀態、主題切換等)來滿足不同的應用場景需求。在下一篇文章中,我們將深入研究 Button.module.scss,進一步探討按鈕的樣式設計,並展示如何結合圖標、加載動畫和彈出提示框來構建更複雜的按鈕組合。
當設計一個按鈕時,你是否考慮過按鈕在不同狀態(如懸停、激活、禁用)下的視覺一致性?你如何確保按鈕在不同主題(如 Light Mode 和 Dark Mode)下保持良好的可讀性和用戶體驗?
在下一篇文章中,我們將帶著你一起體驗如何解決這些問題,通過實際操作來理解按鈕的最佳樣式設計。
完整按鈕元件程式碼已上傳至 GitHub,歡迎查看並實踐。
👉 前往 GitHub 的 Button.jsx 查看完整程式碼。
✨ 流光館Luma<∕> ✨ 期待與你繼續探索更多技術知識!